package common.BaseClasses;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;

import com.lonwin.kmorm.config.ErQueryConfiguration;
import com.lonwin.kmorm.dboperator.sqlaction.CommonSqlOperator;
import com.lonwin.kmorm.dboperator.sqlaction.SqlOperator;
import com.lonwin.kmorm.main.PersistenceManager;
import common.BaseClasses.dao.paged.PagedDaoBase;
import common.BaseClasses.dao.paged.PagedDaoOracleImpl;
import common.BaseClasses.dao.paged.PagedDaoSqlServer2000Impl;
import common.BaseClasses.dao.paged.PagedResultSet;
import common.BaseClasses.util.LogUtils;

/**
 * 数据库访问对象层抽象基类，所有的数据库访问类都要继承于该类，该类中封装了对数据库的操作。
 */
public abstract class CommonDao extends BaseDao {
	
	/**
	 * @see org.apache.commons.dbutils.ResultSetHandler
	 */
	private ResultSetHandler rsh = new MapListHandler();
	
	/**
	 * 是否已自动打开数据库连接。
	 * @return true：已自动打开数据库连接；false：未自动打开数据库连接。
	 * @throws Throwable 抛出异常。
	 */
	private boolean isAutoInitFactory() throws Throwable {
		boolean isAuto = false;
		if (this.getDaoInfo() == null || this.getPm() == null) {
			this.initFactory();
			isAuto = true;
		};
		return isAuto;
	};
	
	/**
	 * 执行insert、update、delete功能的sql语句。
	 * @param sql sql语句。
	 * @return insert或update或delete的记录数。
	 */
	private int executeSQL(String sql) {
		int updateRow = 0;
		try {
			//是否已自动打开数据库连接。
			boolean isAuto = isAutoInitFactory();
			//自动打开数据库连接，则自动开始事物。
			if (isAuto) {
				this.beginTransaction();
			};
			
			if (sql != null) {
				PersistenceManager pm = getPm();
				SqlOperator sqlOperator = new CommonSqlOperator(pm.getConnection());
				updateRow = sqlOperator.executeUpdate(sql);
			};
			
			//自动打开数据库连接，则自动提交事物、自动关闭连接。
			if (isAuto) {
				this.commitTransaction();
				this.closeFactory();
			};
		} catch(Throwable throwable) {
			this.rollbackTransaction();
			this.closeFactory();
			LogUtils.error(throwable);
			throwable.printStackTrace();
		};
		
		return updateRow;
	};
	
	/**
	 * 将whereMap中的信息填入对应的实体类中。
	 * @param entity 实体类。
	 * @param whereMap 要填入实体类中的信息。
	 * @return 已填入信息的实体类。
	 * @throws Throwable 抛出异常。
	 */
	private Object mapToEntity(Object entity, Map<String, Object> whereMap) throws Throwable {
		if (whereMap == null) {
			return entity;
		};

		Method tmpMethod = null;
		String key = null;
		Class<?> attrType = null;
		Object value = null;
		Object[] objs = new Object[1];

		BeanInfo beanInfo = Introspector.getBeanInfo(entity.getClass());
		PropertyDescriptor[] propsDesc = beanInfo.getPropertyDescriptors();
		for (int i = 0; i < propsDesc.length; i++) {
			tmpMethod = propsDesc[i].getWriteMethod();
			attrType = propsDesc[i].getPropertyType();
			key = propsDesc[i].getName();
			if (key.equals("class") || key.equals("clean") || key.equals("deleted") || key.equals("dirty")
					|| key.equals("hollow") || key.equals("instanceIdentity") || key.equals("mainInstance")
					|| key.equals("new") || key.equals("newDeleted") || key.equals("transient")) {
				continue;
			};

			if (whereMap.containsKey(key)) {
				value = whereMap.get(key);									//从map中获取对应的值。
				if (value != null && value.getClass() == String.class) {	//String类型与其它类型的转换处理。
					String strValue = (String) value;
					//非String类型数据,为""时,将其设置为null。
					if ("".equals(value) && attrType != String.class) {
						value = null;
					} else {
						if (attrType == Integer.TYPE || attrType.equals(java.lang.Integer.class)) {
							value = new Integer(Integer.parseInt(strValue));
						} else if (attrType == Long.TYPE || attrType.equals(java.lang.Long.class)) {
							value = new Long(Long.parseLong(strValue));
						} else if (attrType == Double.TYPE || attrType.equals(java.lang.Double.class)) {
							value = new Double(Double.parseDouble(strValue));
						} else if (attrType == Byte.TYPE || attrType.equals(java.lang.Byte.class)) {
							value = new Byte(Byte.parseByte(strValue));
						} else if (attrType == BigDecimal.class) {
							value = new BigDecimal(strValue);
						} else if (attrType == Float.TYPE || attrType.equals(java.lang.Float.class)) {
							value = new Float(Float.parseFloat(strValue));
						} else if (attrType == Date.class) {
							SimpleDateFormat fmtDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
							value = new Date();
							((Date) value).setTime(fmtDate.parse(strValue).getTime());
						} else if (attrType == java.sql.Date.class) {
							SimpleDateFormat fmtDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
							System.out.println("222222::"+strValue);
							Date parse = fmtDate.parse(strValue);
							System.out.println(parse);
							java.sql.Date sqlDate = new java.sql.Date(parse.getTime());
							value = sqlDate;
						} else if (java.sql.Timestamp.class.equals(attrType)) {
							SimpleDateFormat fmtDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
							value = new java.sql.Timestamp(fmtDate.parse(strValue).getTime());
						}else if (value!=null && !"".equals(value) && value.toString().contains("'")) {
							value = value.toString().replaceAll("'", "\"");
						};
					};
				};

				objs[0] = value;
				if (tmpMethod != null) {
					tmpMethod.invoke(entity, objs);
				};
			};
		};
		return entity;
	};
	
	
	/**
	 * 
	 * @param currentPage 当前页的页码（从0开始） × pageSize + 1。
	 * @param pageSize 每页最多显示的记录条数。
	 * @param strQueryFileName sqlm文件路径、名称。
	 * @param whereMap 要进行select的记录的条件，相当于sql语句中where后的内容。
	 * 为可变参数，最多只能有一个元素。
	 * @return Map，元素包括currentPage：当前页码（从1开始）；pageSize：每页最多显示的记录条数；rowsCount：查询出的总记录条数；
	 * pageCount：总页数；还有一个List表示的查询结果集，元素为Map。
	 * @throws Throwable 抛出异常。
	 */
	@SuppressWarnings("unchecked")
	protected final Map<String, Object> selectByfenye(int currentPage, int pageSize
			, String sql, Map<String, Object>... whereMap) throws Throwable {
		ErQueryConfiguration config = null;
		
		Map<String, Object> resultMap = null;
		try {
			boolean isAuto = isAutoInitFactory();
			
			//判断数据库类型
			String databaseType = getDataBaseType(getSystemConnName());
			
			Connection conn = getPm().getConnection();
			conn.setAutoCommit(true);
			Statement stm = conn.createStatement();
			PagedDaoBase dao = null;
			PagedResultSet prs = null;
			
			//根据不同数据库创建不同分页dao
			if("oracle".equals(databaseType)){
				dao = new PagedDaoOracleImpl();
			} else if("sqlserver".equals(databaseType)){
				dao = new PagedDaoSqlServer2000Impl();
			} else {
				throw new Throwable("当前数据库:" + databaseType + "不被支持");
			};
			//执行分页
			prs = dao.getPagedResultSet(stm, sql, currentPage, pageSize);
			
			if(prs == null) {
				throw new Throwable("没有取到分页结果集!");
			};
			
			//存放数据map的list
			List<Object> dataList = (ArrayList<Object>) rsh.handle(prs);
			
			int rowsCount = prs.getTotalRowCount();
			int pageCount = prs.getTotalPageCount();
			
			prs.close();
			
			//封装结果map
			resultMap = new HashMap<String, Object>();
			resultMap.put("currentPage", String.valueOf(prs.getCurrentPage()));	//当前页号
			resultMap.put("pageSize", String.valueOf(pageSize));				//每页的数据行数
			resultMap.put("rowsCount", String.valueOf(rowsCount));				//总的数据行数
			resultMap.put("pageCount", String.valueOf(pageCount));				//总的页数
			resultMap.put("pageableList", dataList);							//当前页的数据集
			
			//如果是自动打开的数据库连接，则自动关闭。
			if (isAuto) {
				this.closeFactory();
			};
		} catch (Throwable throwable) {
			this.closeFactory();
			LogUtils.error(throwable);
			throwable.printStackTrace();
		}
		
		return resultMap;
	};
	
	
};
